{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "9130c10c-b5c6-456c-a6a4-64e8803e0c54",
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f41a3f08-d4d7-4f45-8836-e572b3496d90",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "657\n",
      "492\n"
     ]
    }
   ],
   "source": [
    "# 读取图片\n",
    "img1 = cv2.imread('ori1.png')\n",
    "img2 = cv2.imread('ori2.png')\n",
    "#img1 = cv2.imread('targ1.png')\n",
    "#img2 = cv2.imread('targ2.png')\n",
    "\n",
    "# 指定缩放比例\n",
    "scale_factor = 0.5\n",
    "\n",
    "# 根据缩放比例计算新的宽度和高度值\n",
    "new_width = int(img1.shape[1] * scale_factor)\n",
    "new_height = int(img1.shape[0] * scale_factor)\n",
    "\n",
    "print(new_width)\n",
    "print(new_height)\n",
    "\n",
    "# 进行尺寸调整\n",
    "img1 = cv2.resize(img1, (new_width, new_height))\n",
    "img2 = cv2.resize(img2, (new_width, new_height))\n",
    "\n",
    "# 拼接图片左右显示\n",
    "combined_image = np.hstack((img1, img2))\n",
    "\n",
    "cv2.imshow('original', combined_image)\n",
    "# 显示图像窗口\n",
    "cv2.imshow('My Image', combined_image)\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "626d2fe6-262a-451d-9b30-09ef69cac1a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 灰度化\n",
    "gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)\n",
    "gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)\n",
    "\n",
    "# 拼接图片左右显示\n",
    "combined_gray = np.hstack((gray1, gray2))\n",
    "\n",
    "cv2.imshow('gray', combined_gray)\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "0e9c39cb-c5e3-4558-8fab-aa8bb0b26785",
   "metadata": {},
   "outputs": [],
   "source": [
    "#featureAlg = 'sift'\n",
    "featureAlg = 'orb'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c37b508f-d4b1-4db7-8c54-f28cc8246f2c",
   "metadata": {},
   "outputs": [],
   "source": [
    "if featureAlg != 'sift':\n",
    "    # 创建ORB对象\n",
    "    orb = cv2.ORB_create()\n",
    "else:\n",
    "    # 创建SIFT对象\n",
    "    sift = cv2.xfeatures2d.SIFT_create()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e0fc5628-9445-4e1a-881f-a38ed3a96d08",
   "metadata": {},
   "outputs": [],
   "source": [
    "if featureAlg != 'sift':\n",
    "    kp1, des1 = orb.detectAndCompute(gray1, None)\n",
    "    kp2, des2 = orb.detectAndCompute(gray2, None)\n",
    "else:\n",
    "    kp1, des1 = sift.detectAndCompute(gray1, None)\n",
    "    kp2, des2 = sift.detectAndCompute(gray2, None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1386b1d5-5266-4054-a19f-0c0e9720d722",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "description1 num 500, description2 num 500, match description num 146\n",
      "index[0] match value < cv2.DMatch 000001F7EC1058F0>, distance 25.0\n",
      "index[1] match value < cv2.DMatch 000001F7EC106410>, distance 25.0\n",
      "index[2] match value < cv2.DMatch 000001F7EC1057F0>, distance 26.0\n",
      "index[3] match value < cv2.DMatch 000001F7EC105890>, distance 26.0\n",
      "index[4] match value < cv2.DMatch 000001F7EC1052F0>, distance 29.0\n",
      "index[5] match value < cv2.DMatch 000001F7EC1058D0>, distance 29.0\n",
      "index[6] match value < cv2.DMatch 000001F7EC1059F0>, distance 31.0\n",
      "index[7] match value < cv2.DMatch 000001F7EC1062D0>, distance 31.0\n",
      "index[8] match value < cv2.DMatch 000001F7EC1054B0>, distance 32.0\n",
      "index[9] match value < cv2.DMatch 000001F7EC105330>, distance 33.0\n",
      "index[10] match value < cv2.DMatch 000001F7EC105C30>, distance 34.0\n",
      "index[11] match value < cv2.DMatch 000001F7EC105990>, distance 35.0\n",
      "index[12] match value < cv2.DMatch 000001F7EC105950>, distance 38.0\n",
      "index[13] match value < cv2.DMatch 000001F7EC106170>, distance 38.0\n",
      "index[14] match value < cv2.DMatch 000001F7EC105C50>, distance 41.0\n",
      "index[15] match value < cv2.DMatch 000001F7EC105F70>, distance 41.0\n"
     ]
    }
   ],
   "source": [
    "# 创建匹配器\n",
    "#bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True) # normType MORM_L1\n",
    "#bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True) # normType MORM_L2\n",
    "bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) # normType HAMMING1, ORB二进制才能使用\n",
    "\n",
    "# match 方法返回匹配结果，进行特征匹配\n",
    "match = bf.match(des1, des2)\n",
    "print(\"description1 num {}, description2 num {}, match description num {}\".format(len(des1), len(des2),len(match)))\n",
    "#print(match)\n",
    "# 可以对匹配结果进行进一步处理，比如按照距离排序等\n",
    "match = sorted(match, key=lambda x: x.distance)\n",
    "for i in range(16):\n",
    "    print('index[{}] match value {}, distance {}'.format(i, match[i], match[i].distance))\n",
    "match = match[:15] # 只取16个匹配的点，距离越大越没用。并且，ORB算法匹配到的特征点没有SIFT精确"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "5aa2b852-abfe-44e4-8a16-31fad6341f09",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 绘制匹配点\n",
    "img3 = cv2.drawMatches(img1, kp1, img2, kp2, match, None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f026b4be-9423-4a4a-b01d-9d4ffa4e33ae",
   "metadata": {},
   "outputs": [],
   "source": [
    "if featureAlg == 'sift':\n",
    "    cv2.imshow('sift', img3)\n",
    "else:\n",
    "    cv2.imshow('orb', img3)\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3340eee0-41b7-44d5-956c-44551d76b382",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
